import React, { createContext, useContext, useState, ReactNode, useMemo, useEffect } from 'react';
import { useLocation, Navigate } from 'react-router-dom';
import { Button } from 'antd';
import * as api from '@/api/auth';
import type { EmailLoginDto, UserNameLoginDto } from '@/api/auth';
import { userCreate, userSelfInfo } from '@/api/user';
import type { CreateUserDto } from '@/api/user';

interface IAuthContext {
    user: any;
    getSelfInfo: () => Promise<any>;
    signin(params: EmailLoginDto): Promise<any>;
    signin(params: UserNameLoginDto): Promise<any>;
    signup: (body: CreateUserDto) => Promise<any>;
    signout: () => Promise<any>;
}

export const AuthContext = createContext<IAuthContext>(null!);

/**
 * 上下文Provider
 * @param {*} param0
 * @returns
 */
export function AuthProvider({ children }: { children: ReactNode }) {
    // 将用户信息存到context
    const [user, setUser] = React.useState<any>(null);

    const value = useMemo(() => {
        // 获取用户信息
        const getSelfInfo = async () => {
            try {
                const res: any = await userSelfInfo();
                if (res.code === 0) {
                    // 更新信息
                    setUser(res.data);
                }
            } catch (error) {
                // 获取信息失败，清空信息
                localStorage.clear();
                setUser(null);
            }
        };
        // 登录
        const signin = async (params: UserNameLoginDto | EmailLoginDto) => {
            let res: any;
            if ('username' in params && 'password' in params) {
                const { username, password } = params;
                res = await api.login({
                    type: 'username',
                    username,
                    password,
                });
            } else if ('email' in params && 'code' in params) {
                const { email, code } = params;
                res = await api.login({
                    email,
                    code,
                    type: 'email',
                });
            }

            if (res.code === 0) {
                localStorage.setItem('access_token', res.data.access_token);
            }
            return res;
        };
        // 注册
        const signup = async (body: CreateUserDto) => {
            const res: any = await userCreate(body);
            if (res.code === 0) {
                localStorage.setItem('access_token', res.data.access_token);
            }
            return res;
        };
        // 注销
        const signout = async () => {
            localStorage.clear();
            setUser(null);
            return Promise.resolve(true);
        };

        return { user, getSelfInfo, signin, signup, signout };
    }, [user]);

    return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

/**
 * 获取上下文
 * @returns
 */
export function useAuth() {
    return useContext(AuthContext);
}

/**
 * 如何使用demo 查看状态
 * @returns
 */
export function AuthStatus() {
    const { user, signout } = useAuth();

    if (!user) {
        return <p>未登录</p>;
    }

    return (
        <div>
            <span className='mr-2'>
                欢迎
                {user.username}
            </span>
            <Button
                onClick={async () => {
                    signout();
                }}
            >
                注销
            </Button>
        </div>
    );
}

/**
 * 高阶组件-没登录跳转到登录页
 * @param {*} param0
 * @returns
 */
export function RequireAuth({ children }: { children: ReactNode }) {
    const { user, getSelfInfo } = useAuth()!;

    const location = useLocation();
    const [initialized, setInitialized] = useState(false);
    const token = localStorage.getItem('access_token');

    useEffect(() => {
        if (!initialized && token && !user) {
            getSelfInfo();
            setInitialized(true);
        }
    }, [token, user, initialized, getSelfInfo]);

    if (!token) {
        return <Navigate to='/login' state={{ from: location }} replace />;
    }

    return initialized ? children : null;
}
